from datetime import datetime

from django.db import models
from ckeditor.fields import RichTextField
from django.conf import settings
from django.shortcuts import reverse



class Keyword(models.Model):
    """关键词"""
    name = models.CharField('文章关键词', max_length=50, help_text='关键词')

    class Meta:
        verbose_name = '关键词'
        verbose_name_plural = '关键词'
        ordering = ['name']

    def __str__(self):
        return self.name


class Tag(models.Model):
    """文章标签"""
    name = models.CharField(max_length=100, blank=False, null=False, unique=True, default='标签', help_text='标签名称')
    description = models.CharField(max_length=200, blank=True, null=True, default='标签描述', help_text='标签描述')
    slug = models.SlugField(max_length=50, unique=True, help_text='标签别名')

    class Meta:
        verbose_name = '标签'
        verbose_name_plural = '标签'

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('tag', args=[self.slug])

    def get_article_list(self):
        return Article.objects.filter(tags=self, is_published=True)


class Category(models.Model):
    """文章分类"""
    name = models.CharField('分类名', max_length=30, default='分类', help_text='分类名称')
    description = models.CharField('分类描述', max_length=240, default='分类描述', help_text='分类描述,用于作为SEO中的description')
    slug = models.SlugField(max_length=100, unique=True, help_text='分类别名')

    class Meta:
        verbose_name = '分类'
        verbose_name_plural = '分类'
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('blog:category', kwargs={'slug': self.slug})

    def get_article_list(self):
        return Article.objects.filter(category=self, is_published=True)


class Subject(models.Model):
    """专题"""
    STATUS_CHOICES = (
        ('not_start', '未开始'),
        ('ongoing', '连载中'),
        ('completed', '已完结'),
    )
    name = models.CharField('专题名', max_length=60, help_text='专题名称')
    status = models.CharField('专题状态', max_length=10, choices=STATUS_CHOICES, default='not_start', help_text='专题状态')
    description = models.CharField('专题描述', max_length=240)
    sort_order = models.IntegerField('排序', default=9, help_text='专题排序')
    create_time = models.DateTimeField('创建时间', auto_now_add=True, help_text='专题创建时间')
    update_time = models.DateTimeField('修改时间', auto_now=True, help_text='专题修改时间')
    cover_img = models.ImageField('封面图', upload_to='subject/%Y/%m/%d/', help_text='专题封面图')

    class Meta:
        verbose_name = '专题'
        verbose_name_plural = '专题'
        ordering = ['sort_order']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('blog:subject_page', kwargs={'pk': self.pk})

    def get_topics(self):
        """获取专题下的所有主题"""
        return Topic.objects.filter(subject=self).order_by('sort_order', '-pk')

    def get_article_count(self):
        """获取专题下的所有文章数"""
        num = 0
        for each in self.get_topics():
            num += each.get_articles().count()
        return num

    def get_article_list(self):
        """获取专题下的所有文章"""
        article_list = []
        for topic in self.get_topics():
            article_list.extend(topic.get_articlest())
        return article_list

    def get_status_color(self):
        text_dict = {
            'not_start': 'danger',
            'ongoing': 'info',
            'completed': 'success',
        }
        return text_dict[self.status]


class Topic(models.Model):
    """专题中的主题"""
    name = models.CharField('主题名', max_length=60, help_text='主题名称')
    create_time = models.DateTimeField('创建时间', auto_now_add=True, help_text='主题创建时间')
    update_time = models.DateTimeField('修改时间', auto_now=True, help_text='主题修改时间')
    sort_order = models.IntegerField('排序', default=9, help_text='主题排序,用于在专题中显示主题的排序')
    subject = models.ForeignKey(Subject, verbose_name='所属专题', related_name='topics',
                                on_delete=models.PROTECT, help_text='所属专题')

    class Meta:
        verbose_name = '专题-主题'
        verbose_name_plural = verbose_name
        ordering = ['sort_order']

    def __str__(self):
        return f'[{self.subject.name}]{self.name}'

    def get_absolute_url(self):
        return reverse('blog:subject_page', kwargs={'pk': self.subject.pk}) + f'#{self.name}'

    def get_articles(self):
        """获取主题下的所有文章,按照主题排序进行排序 """
        return Article.objects.filter(topic=self, is_published=True).order_by('sort_order', '-pk')


class Article(models.Model):
    """文章"""
    title = models.CharField('标题', max_length=100, help_text='文章标题')
    summary = models.TextField('文章摘要', max_length=230, default='文章摘要等同于网页description内容，请务必填写...')
    body = RichTextField('正文', help_text='文章正文')
    create_time = models.DateTimeField('创建时间', auto_now_add=True, help_text='文章创建时间')
    update_time = models.DateTimeField('修改时间', auto_now=True, help_text='文章修改时间')
    author = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='作者', on_delete=models.CASCADE, help_text='文章作者')
    views = models.PositiveIntegerField('浏览量', default=0, help_text='文章浏览量')
    is_published = models.BooleanField('是否发布', default=True, help_text='文章是否发布')
    is_top = models.BooleanField('是否置顶', default=False, help_text='文章是否置顶')
    slug = models.SlugField(unique=True)

    category = models.ForeignKey(Category, verbose_name='分类', on_delete=models.PROTECT, help_text='文章分类')
    tags = models.ManyToManyField(Tag, verbose_name='标签')
    keywords = models.ManyToManyField(Keyword, verbose_name='关键词',
                                      help_text='文章关键词，用来作为SEO中的keywords，最好长尾词，3-4个')

    # 专题主题等为非必填字段
    topic = models.ForeignKey(Topic, verbose_name='所属主题', blank=True, null=True,
                              on_delete=models.SET_NULL, related_name='articles')
    topic_order = models.IntegerField('主题中排序', default=9, blank=True, null=True,
                                      help_text='主题排序,用于在主题中显示文章的排序')
    topic_short_title = models.CharField('主题短标题', max_length=50, blank=True, null=True,
                                         help_text='给Topic使用的短标题')

    class Meta:
        verbose_name = '文章'
        verbose_name_plural = '文章'
        ordering = ['-create_time']

    def __str__(self):
        return f'{self.title[:30]}...' if len(self.title) > 30 else self.title

    def save(self, *args, **kwargs):
        if self.pk and self.is_published and Article.objects.filter(pk=self.pk, is_published=False).exists():
            # 如果之前是未发布的，现在变成发布状态，那么浏览量清零
            self.create_time = datetime.now()
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        """优先使用专题地址"""
        # if self.topic:
        #     return self.topic.get_absolute_url()
        return reverse('blog:detail', kwargs={'slug': self.slug})

    def get_subject_absolute_url(self):
        """获取专题地址"""
        return reverse('blog:subject_detail', kwargs={'slug': self.slug})

    def update_views(self):
        """更新浏览量"""
        self.views += 1
        self.save(update_fields=['views'])

    def get_pre(self):
        """
        获取上一篇文章
        如果有主题则只返回这个主题下的文章，否则返回空，没有主题则按pk排序
        """
        if self.topic:
            subject_articles = self.topic.subject.get_article_list()
            for index, article in enumerate(subject_articles ):
                if article.pk == self.pk and index != 0:
                    return subject_articles[index - 1]
            return
        return Article.objects.filter(id__lt=self.id, is_publish=True).order_by('-id').first()

    def get_next(self):
        """
        获取下一篇文章
        """
        if self.topic:
            subject_articles = self.topic.subject.get_article_list()
            for index, article in enumerate(subject_articles):
                if article.pk == self.pk and index != len(subject_articles) - 1:
                    return subject_articles[index + 1]
            return
        return Article.objects.filter(id__gt=self.id, is_publish=True).order_by('id').first()

    def get_topic_title(self):
        """获取专题标题"""
        if self.topic:
            return self.topic_short_title or self.title
        return self.title


class FriendLink(models.Model):
    """友链"""
    name = models.CharField('网站名称', max_length=50, help_text='网站名称')
    description = models.CharField('网站描述', max_length=240, help_text='网站描述')
    link = models.URLField('网站链接', help_text='网站链接')
    logo = models.CharField('网站LOGO', default='https://leedu.ac.cn/static/favicon-32x32.png', help_text='网站LOGO', max_length=255)
    create_time = models.DateTimeField('创建时间', auto_now_add=True, help_text='友链创建时间')
    is_active = models.BooleanField('是否有效', default=True, help_text='友链是否激活')

    class Meta:
        verbose_name = '友链'
        verbose_name_plural = '友链'
        ordering = ['create_time']

    def __str__(self):
        return self.name

    def active_to_false(self):
        self.is_active = False
        self.save(update_fields=['is_active'])
